package com.tool.tab;

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinUser;
import com.sun.jna.win32.StdCallLibrary;
import com.updateNew.MyIsif;
import org.come.npc.Sleep;
import org.come.socket.GameClient;

import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.*;
import java.util.concurrent.TimeUnit;

public class Main {
    public static TabJFrame tabJFrame;
    private static Button bt;
    /**
     * 如果你需要在IDEA内运行就把这个设位 true
     * 如果你需要出包做登录器就把这个设为 false
     */
    public static boolean debug = false;//出包false，idea运行true
    public static String dir = System.getProperty("user.dir");
    public static WinDef.HWND showHWND;
    public static WinDef.HWND ts = null;
    public static boolean exit = false;
    public static boolean addIng = true;
    public static int lastX = -1;
    public static int lastY = -1;
    public static String title = GameClient.BT;//设置多开器顶部文字内容
    //    public static String title = "大话西游2经典版";//设置多开器顶部文字内容
    private static Main instance = null;
    public static String tabName = null;

    public static Map<Integer, WinDef.HWND> hwnds = new HashMap<>();

    public static Main getInstance() {
        return instance;
    }

    public static void main(String[] args) {
        MyIsif.ifs = "DK";
        // 创建TabJFrame对象
        tabJFrame = new TabJFrame();
        // 刷新角色
        tabJFrame.customTitleBarUI.refreshRoles();
        // 设置窗口可见
        tabJFrame.setVisible(true);
        // 启动TabJFrame
        Main.tabJFrame.start = true;
        tabJFrame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                // 改进的进程销毁逻辑
                tabJFrame.games.forEach((k, p) -> {
                    try {
                        // 先尝试正常关闭
                        p.destroy();
                        // 等待进程结束，最多等待5秒
                        if (!p.waitFor(5, TimeUnit.SECONDS)) {
                            // 如果5秒内未结束，强制关闭
                            p.destroyForcibly();
                            p.waitFor(1, TimeUnit.SECONDS);
                        }
                    } catch (InterruptedException ex) {
                        p.destroyForcibly();
                        Thread.currentThread().interrupt(); // 恢复中断状态
                    } catch (Exception ex) {
                        // 强制销毁作为最后手段
                        try {
                            p.destroyForcibly();
                        } catch (Exception ignored) {
                        }
                    }
                });
                exit = true;
                // 清理TCP资源
                try {
                    com.tool.tcp.SpriteFactory.shutdownTcpLoadThread();
                } catch (Exception ex) {
                    // 忽略异常
                }
                // 清理缓存
                try {
                    org.come.until.UserMessUntil.clearAllCache();
                } catch (Exception ex) {
                    // 忽略异常
                }
                new Timer().schedule(new TimerTask() {
                    @Override
                    public void run() {
                        System.exit(0);
                    }
                }, 1000L);
            }
        });
        // 恢复原始的窗口焦点监听器
        tabJFrame.addWindowFocusListener(new WindowAdapter() {
            @Override
            public void windowGainedFocus(WindowEvent e) {
                User32.INSTANCE.AttachThreadInput(
                        new WinDef.DWORD(User32.INSTANCE.GetWindowThreadProcessId(ts, null)),
                        new WinDef.DWORD(User32.INSTANCE.GetWindowThreadProcessId(showHWND, null)),
                        true);
            }
        });
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            tabJFrame.games.forEach((k, p) -> {
                try {
                    // 先尝试正常关闭
                    p.destroy();
                    // 等待进程结束，最多等待3秒
                    if (!p.waitFor(3, TimeUnit.SECONDS)) {
                        // 如果3秒内未结束，强制关闭
                        p.destroyForcibly();
                        p.waitFor(1, TimeUnit.SECONDS);
                    }
                } catch (InterruptedException ex) {
                    p.destroyForcibly();
                    Thread.currentThread().interrupt(); // 恢复中断状态
                } catch (Exception ex) {
                    // 强制销毁作为最后手段
                    try {
                        p.destroyForcibly();
                    } catch (Exception ignored) {
                    }
                }
            });
            exit = true;
        }));
        // 这段代码可能是 Java 应用程序的线程，该线程负责更新自定义标题栏的 UI。下面是加上注释后的代码：
        new Thread(() -> {
            while (!exit) {
                tabJFrame.customTitleBarUI.repaint();
                try {
                    // 改进的进程清理机制
                    for (Iterator<Map.Entry<Integer, Process>> iterator = tabJFrame.games.entrySet().iterator();
                         iterator.hasNext();
                    ) {
                        Map.Entry<Integer, Process> entry = iterator.next();
                        hwnds.put(entry.getKey(), null);
                        Process process = entry.getValue();

                        // 检查进程是否还活着
                        if (!process.isAlive()) {
                            try {
                                // 确保进程被完全销毁
                                process.destroyForcibly();
                            } catch (Exception e) {
                                // 忽略销毁过程中的异常
                            }
                            // 从管理器中移除游戏
                            tabJFrame.removeGame(entry.getKey());
                            iterator.remove();
                            // 同时清理hwnd引用
                            hwnds.remove(entry.getKey());
                        }
                    }
                    // 这段代码用于在 Java 程序中控制一个子进程（子线程）的位置。下面是加上注释后的代码：
                    if (tabJFrame.getX() != lastX ||
                            tabJFrame.getY() != lastY) {
                        // 获取当前选中的游戏进程
                        Process process = tabJFrame.games.get(tabJFrame.getShouId());
                        // 尝试将当前窗口的 X 坐标和 Y 坐标发送给游戏进程的输出流
                        try {
                            process.getOutputStream().write((tabJFrame.getX() + ":" + tabJFrame.getY() + "\n").getBytes());
                            process.getOutputStream().flush();
                            // 更新上次窗口位置
                            lastY = tabJFrame.getY();
                            lastX = tabJFrame.getX();
                        } catch (Exception e) {
                            // 忽略异常
                        }
                    }
                    // 这段代码用于将多个子窗口移动到一个父窗口中，代码主要包括以下几个步骤：
                    // 1. 判断当前游戏列表是否为空，如果为空则退出程序
                    // 2. 如果 ts 为空，则查找一个名为 SunAwtFrame 的窗口，并将其赋值给 ts
                    // 3. 如果 hwnds 包含值为 null 的键值对，则遍历 hwnds，并使用 FindWindow 找到相应的窗口，并将其设置为父窗口
                    // 4. 使用 SetParent 重新设置窗口的父窗口
                    if (tabJFrame.games.size() <= 0) System.exit(0);
                    if (ts == null) ts = User32.INSTANCE.FindWindow("SunAwtFrame", title);
                    if (hwnds.containsValue(null)) {
                        hwnds.forEach((k, v) -> {
                            WinDef.HWND hWnd = User32.INSTANCE.FindWindow("SunAwtFrame", GameClient.BT + k + tabName);
                            if (hWnd != null) {
                                User32.INSTANCE.SetParent(hWnd, ts);
//                                WinDef.RECT qqwin_rect = new WinDef.RECT();
//                                User32.INSTANCE.GetWindowRect(hWnd, qqwin_rect);
//                                int width = Math.max(qqwin_rect.right - qqwin_rect.left, 800);
//                                int height = Math.max(qqwin_rect.bottom - qqwin_rect.top , 600);
//                                User32.INSTANCE.MoveWindow(hWnd, 0, 22, width, height, true);
//                                User32.INSTANCE.SetWindowLongPtr(hWnd, -16, Pointer.createConstant(0x00C00000L & 0x00080000L & 0x00040000L));
                                User32.INSTANCE.SetWindowPos(hWnd, null
                                        , 0, 0, 0, 0, 0x0004 | 0x0080 | 0x0001 | 0x0002);
                            }
                        });
                    }
                    // 这段代码用于遍历当前活动桌面上的所有窗口，并找到与指定的窗口标题（GameClient.BT + tabJFrame.getShouId() + tabName）匹配的窗口。如果找到的窗口不在可视状态，则将其显示出来。下面是加上注释后的代码：
                    User32.INSTANCE.EnumChildWindows(ts, (hWnd, arg1) -> {
                        // 创建一个字节数组，用于存储窗口的文本信息
                        byte[] windowText = new byte[512];
                        // 使用 User32_2.INSTANCE.GetWindowTextA() 函数获取窗口的文本信息，并将其存储在 windowText 数组中
                        User32_2.INSTANCE.GetWindowTextA(hWnd, windowText, 512);
                        // 使用 Native.toString() 函数将字节数组转换为字符串，并使用 GBK 字符集进行解码
                        String title = Native.toString(windowText, "GBK");
                        // 如果找到的窗口的标题等于指定的窗口标题，并且该窗口不在可视状态，则执行以下操作
                        if (title.equals(GameClient.BT + tabJFrame.getShouId() + tabName)) {
                            if (!User32.INSTANCE.IsWindowVisible(hWnd)) {
                                // 保存找到的窗口句柄
                                showHWND = hWnd;
                                // 使用 User32.INSTANCE.ShowWindow() 函数将窗口显示出来
                                User32.INSTANCE.ShowWindow(hWnd, 9);
                            }
                            // 创建一个 WinDef.RECT 结构体，用于存储窗口的位置和大小信息
                            WinDef.RECT qqwin_rect = new WinDef.RECT();
                            // 使用 User32.INSTANCE.GetWindowRect() 函数获取窗口的位置和大小信息，并将其存储在 qqwin_rect 结构体中
                            User32.INSTANCE.GetWindowRect(hWnd, qqwin_rect);

                            // 定义一个变量，用于存储初始窗口宽度
                            int initWidth = 1026;

                            // 定义一个变量，用于存储窗口的宽度
                            int tmpWidth = qqwin_rect.right - qqwin_rect.left;
                            // 如果窗口的宽度为 806，则将其设置为 806
                            if (tmpWidth == 806) {
                                tmpWidth = 806;
                                initWidth = 806;
                            }


                            // 使用 Math.max() 函数获取窗口的最大宽度
                            int width = Math.max(tmpWidth, initWidth);
                            // 使用 Math.max() 函数获取窗口的最大高度
                            int height = Math.max(qqwin_rect.bottom - qqwin_rect.top, 720);
                            //User32.INSTANCE.MoveWindow(hWnd, 3, 34, width, height, true);
                            // 定义一个变量，用于存储窗口的最小高度
                            int min = Math.min(height + 48, 835);
                            // 如果窗口的高度为 595，则将其设置为 660
                            if (qqwin_rect.bottom - qqwin_rect.top == 595) {
                                tabJFrame.setSize(tmpWidth+10, 660);
                                tabJFrame.customTitleBarUI.setSize(tmpWidth+10, 662);
                            } else if(qqwin_rect.bottom - qqwin_rect.top==710){
                                tabJFrame.setSize(width == 1026 ? width : width + 10, width == 1026 ? 768 : 831);
                                tabJFrame.customTitleBarUI.setSize(width == 1026 ? width : width + 10, width == 1026 ? 768 : 833);
                            }else if (width == 1026) {
                                tabJFrame.setSize(width ,770);
                                tabJFrame.customTitleBarUI.setSize(width , 770);
                            } else {
                                tabJFrame.setSize(width-2, 830);
                                tabJFrame.customTitleBarUI.setSize(width, 830);
                            }
                        } else {
                            // 如果找到的窗口的标题不等于指定的窗口标题，并且该窗口在可视状态，则执行以下操作
                            if (User32.INSTANCE.IsWindowVisible(hWnd)) User32.INSTANCE.ShowWindow(hWnd, 0);
                        }
                        // 返回 true，继续遍历下一个窗口
                        return true;
                    }, null);
                    Thread.sleep(50);
                } catch (InterruptedException | NullPointerException e) {
                    // e.printStackTrace(); // 减少日志输出
                }
            }
        }).start();
    }

    public interface User32_2 extends StdCallLibrary {
        User32_2 INSTANCE = (User32_2) Native.loadLibrary("user32", User32_2.class);

        boolean EnumWindows(WinUser.WNDENUMPROC lpEnumFunc, Pointer arg);

        int GetWindowTextA(WinDef.HWND hWnd, byte[] lpString, int nMaxCount);
    }
}
